import java.awt.Color;
import java.awt.Graphics;
import java.text.DecimalFormat;

import javax.swing.JOptionPane;
import javax.swing.JPanel;



/**
 * Die Klasse repraesentiert ein JPanel mit ueberschriebener
 * "paintComponent(Grapics g)"-Methode Diese Methode wird standardmaessig beim
 * Neuzeichnen aufgerufen und bekommt von Oben das Graphics-Objekt uebergeben,
 * welches auf die Oberlaeche zeichnen kann
 * 
 * @author Fabian
 * @date 26.10.2012
 * 
 */
public class PaintingComponent extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// Einheiten fuer x- und y-Achse sind identisch
	// Falls das geaendert werden soll muss sowohl die Beschriftung der Achsen,
	// als auch die Zeichnung einer FUnktion ueberarbeitet werden.;
	private boolean firstRun = true;

	// Durch die aufteilung von EinheitProPixel in EinheitProPixelX und
	// EinheitProPixelY, kann das Koordinatensystem auch nur den x-Bereich oder
	// den y-Bereich vergroessssern oder verkleinern.
	private int abstand = 20;
	private double EinheitProPixelX = 1.0 / abstand;
	private double EinheitProPixelY = 1.0 / abstand;
	private int middlePointX;
	private int middlePointY;
	private Funktion erloesFunktion = null;
	private Funktion kostenFunktion = null;
	private int randAbstand=25;
	private boolean markierungen = false;
	private boolean difference = false;
	private Logik logik = new Logik();
	
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (firstRun) {
			middlePointX = this.getWidth() / 2;
			middlePointY = this.getHeight() / 2;
			firstRun = false;
		}
		this.setBackground(Color.WHITE);

		if(erloesFunktion!=null){
			logik.setErloesfunktion(zeichneFunktion(g, erloesFunktion));
		}
		if(kostenFunktion!=null){
			logik.setKostenfunktion(zeichneFunktion(g, kostenFunktion));
		}
		if(markierungen){
			if(areBothFunctionsSet()){
				faerbeFlaechen(g, erloesFunktion, kostenFunktion);
				drawMaxErloes(g);
				drawSchnittpunkte(g);
			}
			if(erloesFunktion!=null){
				drawMaxGewinn(g);
			}
			if(kostenFunktion!=null){
				drawMaxVerlust(g);
			}
		}
		if(difference){
			drawDiff(g);
		}
		
		drawCoordinationSystem(g);

	}

	/**
	 * Diese Methode stellt ein kartesisches Koordinatensystem mit dem Ursprung
	 * im "(middlePointX | middlePointY)" dar. 
	 * Es sorgt für die richtige Beschriftung der Achsen bei einem geben Abstand der Striche, welche eine Einheit darstellen.
	 * Die Beschriftung orientiert sich dabei nach den globalen Werten EinheitProPixelX / -Y.
	 * 
	 * 
	 * TODO: Eventuell ueberlegen ob Eigenschaften wie
	 * abstand oder Beschriftung mit uebergeben werden.
	 * 
	 * @param g
	 */
	private void drawCoordinationSystem(Graphics g) {
		g.setColor(Color.BLACK);
		int startXAchse = 0;
		int endXAchse = 0;
		int startYAchse = 0;
		int endYAchse = 0;
		int posXAchse = middlePointY;
		int posYAchse = middlePointX;
		int vorzeichenX = -1;
		int vorzeichenY = -1;
		int counter = 0;
		int x = randAbstand;
		int y = randAbstand;
		int strichLaenge = 6;
		int beschriftung = 2; //Jeder 2te Strich wird beschriftet
		String s = "";
		DecimalFormat df = new DecimalFormat("0.##");
		
		
		/*
		 * Aussehen des Koordinatensystems festlegen, je nachdem wo der Mittelpunkt liegt
		 * 
		 * Fals der Mittelpunkt ausserhalb des sichtbaren Bereichs liegt, sol die theoretisch verschwundene Achse dennoch statisch am Rand angezeigt werden.
		 * 
		 */
		if(middlePointX <= randAbstand){
			vorzeichenX = -1;
			startXAchse = 0;
			endXAchse = this.getWidth() - randAbstand;
			posYAchse = randAbstand;
		}
		else if(middlePointX >= this.getWidth() -randAbstand){
			vorzeichenX = 1;
			startXAchse = this.getWidth();
			endXAchse = randAbstand;
			posYAchse = this.getWidth() - randAbstand;
		}
		else{
			vorzeichenX = -1;
			startXAchse = 0;
			endXAchse = this.getWidth() - randAbstand;
			posYAchse = middlePointX;
		}
		if(middlePointY <= randAbstand){
			vorzeichenY = -1;
			startYAchse = 0;
			endYAchse = this.getHeight() - randAbstand;
			posXAchse = randAbstand;
		}
		else if(middlePointY >= this.getHeight() - randAbstand){
			vorzeichenY = 1;
			startYAchse = this.getHeight();
			endYAchse = randAbstand;
			posXAchse = this.getHeight() - randAbstand;
		}
		else{
			vorzeichenY = 1;
			startYAchse = this.getHeight() ;
			endYAchse = randAbstand;
			posXAchse = middlePointY;
		}
		//X-Achse
		g.drawLine(startXAchse, posXAchse, endXAchse, posXAchse);
		//Pfeil am Ende der X-Achse
		g.drawLine(endXAchse, posXAchse, endXAchse + vorzeichenX * 5, posXAchse + 5);
		g.drawLine(endXAchse, posXAchse, endXAchse + vorzeichenX * 5, posXAchse - 5);
		g.drawString("X", endXAchse + vorzeichenX * 5, posXAchse + 20);
		
		//Y-Achse
		g.drawLine(posYAchse, startYAchse, posYAchse, endYAchse);
		//Pfeil am Ende der Y-Achse
		g.drawLine(posYAchse, endYAchse, posYAchse + 5, endYAchse + vorzeichenY * 5);
		g.drawLine( posYAchse, endYAchse, posYAchse - 5, endYAchse + vorzeichenY * 5);
		g.drawString("Y", posYAchse  + 10, endYAchse + vorzeichenY * 15);		
		
		
		//Beschriftung der X-Achse
		counter = (middlePointX - randAbstand - (middlePointX - randAbstand)%abstand)/ (-abstand);
		x = randAbstand + (middlePointX - randAbstand) % abstand;
		System.out.println(this.getWidth());
		System.out.println("counter: "+counter+ ", x: "+x);
		while (x < this.getWidth() - randAbstand) {
			System.out.println(counter);
			g.drawLine(x, posXAchse - (strichLaenge / 2), x, posXAchse+ (strichLaenge / 2));
			if (counter != 0 && Math.abs(counter) % beschriftung == 0) {
				s = "" + df.format(counter * abstand * EinheitProPixelX);
				g.drawString(s, x - (s.length() * 3), posXAchse + 15);
			}
			x += abstand;
			counter++;
		}
		
		//Beschriftung der y-Achse
		counter = (this.getHeight() - middlePointY - randAbstand - (this.getHeight() - middlePointY - randAbstand)%abstand)/ (-abstand);
		y = this.getHeight() - randAbstand - (this.getHeight() - middlePointY - randAbstand) % abstand;
		System.out.println(this.getWidth());
		System.out.println("counter: "+counter+ ", x: "+x);
		while (y > randAbstand) {
			System.out.println(counter);
			g.drawLine(posYAchse - (strichLaenge / 2), y, posYAchse+ (strichLaenge / 2),  y);
			if (counter != 0 && Math.abs(counter) % beschriftung == 0) {
				s = "" + df.format(counter * abstand * EinheitProPixelY);
				g.drawString(s, posYAchse - 10 - (s.length() * 7), y+5);
			}
			y -= abstand;
			counter++;
		}
	}
	
	
	
	/**
	 * Zeichnet die uebergeben Funktion in das Fenster, abhängig von den Zurzeit global gültigen Paramtern wie
	 * 	--Position des Mittelpunktes
	 * 	--Einheit Pro Pixel
	 *  --Abstand der Einheiten auf der Skala
	 * 
	 * @param g Graphics-Komponente: Auf dieser soll im Endeffekt gezeichnet werden
	 * @param function Zu zeichnende Funktion vom eigenen Typ Function
	 * @return Eine Liste von Punkten, die fuer die Auswertung der Funktion benoetigt wird. Um eine solche Liste nicht zu einem spaeteren Zeitpunkt erneut anlegen zu muessen,
	 * wird Sie hier erstellt und die Punkte, die sowieso berechnet werden muessen, muessen nur zusaetzlich gespeichert werden. 
	 */
	private double[][] zeichneFunktion(Graphics g, Funktion function) {		
		int x = 0;
		// schrittweit(in Pixeln) in denen ein neuer Punkt erstelt wird.
		// Zwischen den Punkten werden Linien gezeichnet
		int schrittweite = 5;
		// aktueller und letzter Punkt muessen gespeichert werden um eine Linie
		// zwischen Ihnen zu zeichnen
		int aktY = 0;
		int lastY =0;
		boolean ersterDurchlauf=true;
		boolean error=false;
		double[][] werte = new double[((this.getWidth()-20)/schrittweite)+1][2];
		/*
		 * Erklaerung zu der Berechnung eines neuen Punktes: zunaechst muss x
		 * in Relation zum Mittelpunkt gesetzt werden und anschliessend zu
		 * einem x relativ zur Momentanen Pixeleinheit umgerechnet werden Zu
		 * diesem "reelen X-Wert" wird anschliessend ueber das "getY()" der
		 * Funktion der y-Wert geholt. Da die graphische Oberflaeche ein
		 * Koordinatensystem verwendet das so (0|0)
		 * |-------------------------------------------> X | | | | x
		 * *middlePoint(200|200) | | \/ Y Ist leicht ersichtlich das die y-Achse
		 * gespiegelt zum Kartesischem Koordinatensystem ist. => ermittelter
		 * Y-Wert * (-1) Anschliessend muss der Punkt noch relativ zum
		 * Mittelpunkt unseres Kartesischen Koordinatensystem in y-Richtung
		 * verschoben werden.
		 */	
		while (x <= this.getWidth() - 20) {
			werte[x/schrittweite][0]=realX2VirtX(x);
			try{
				werte[x/schrittweite][1]=function.berechne(werte[x/schrittweite][0]);
				aktY = virtY2RealY(werte[x/schrittweite][1]);
			}
			catch(Funktion.DoNotPaintException e){
				ersterDurchlauf=true;
				error=true;
				werte[x/schrittweite][1]=Double.NaN;
			}
			if(!ersterDurchlauf){
				if(function.isAktFunktion()){
					if(x%10 < 5){		
						g.setColor(Color.blue);
						g.drawLine(x - schrittweite, lastY, x, aktY);
					}
				}
				else{
					g.setColor(Color.red);
					g.drawLine(x - schrittweite, lastY, x, aktY);
				}
			}
			lastY = aktY;
			if(!error){
				ersterDurchlauf=false;
			}
			
			x += schrittweite;
			error=false;
		}
		//Testausgabe von werte!!!
		for(int i=0;i<werte.length;i++){
			for(int z=0; z<werte[0].length;z++){
				System.out.print("werte["+i+"]["+z+"]: "+werte[i][z]+" , ");
			}
			System.out.println("");
		}
		return werte;
	}
	
	/**
	 * Diese Funktion zeichnet eine Liste von gegebenen Punkten und verbindet diese
	 * 
	 * TODO: Evtl. sinnvoll Liste vorher zu sortieren, da so eine chaotische Reihenfolge vermieden wird
	 * @param g Graphics-Komponente: Auf dieser soll im Endeffekt gezeichnet werden
	 * @param punkte Liste von zu zeichnenden Punkten
	 */
	public void zeichnePunkte(Graphics g,double[][] punkte){
		for(int i=1; i<punkte.length;i++){
			if(!Double.isNaN(punkte[i-1][0])||!Double.isNaN(punkte[i][0])){
				g.drawLine(virtX2RealX(punkte[i-1][0]), virtY2RealY(punkte[i-1][1]), virtX2RealX(punkte[i][0]), virtY2RealY(punkte[i][1]));
			}
		}
	}
	/**
	 * Faerbt den Berich zwischen der uebergeben Erloes- und Kostenfunktion, je nachdem ob es sich gerade um einen "Gewinn abwerfenden"- oder "Verlust machenden"-Bereich handelt.
	 * @param g Graphics-Komponente: Auf dieser soll im Endeffekt gezeichnet werden
	 * @param erloes Die vom Benutzer eingegebene Erloesfunktion. 
	 * @param kosten Die vom Benutzer eingegeben Kostenfunktion
	 */
	public void faerbeFlaechen(Graphics g, Funktion erloes, Funktion kosten){		
		/*
		 * Schnitt[] bekommt die Schnittpunkte der beiden Funktionen aus dem Vergleich
		 * Schnittpunkte[] bekommt noch einen Startwert und einen Endwert dazu. Mit diesen Werten wird am Ende gerechnet
		 */
		double schnitt[] =   logik.getVergleich().getSchnitteX();
		double schnittpunkte[]= new double[schnitt.length+2];
		if(schnitt.length > 0 && virtX2RealX(schnitt[0])<30){
			schnittpunkte[0]=schnitt[0];
		}
		else{
			schnittpunkte[0]=realX2VirtX(30);
		}
		for(int z=0;z<schnitt.length;z++){
			schnittpunkte[z+1]=schnitt[z];
		}
		schnittpunkte[schnittpunkte.length-1]=realX2VirtX(this.getWidth()-20);
		for(int z=0;z<schnittpunkte.length;z++){
			System.out.println("z: "+z+"--> "+schnittpunkte[z]);
		}
		int x[] = new int[3];
		int y[] = new int[3];
		int nextSchnittpunkt=0;
		
		/*
		 * Es wird immer von einem Schnittpunkt zum nächsten gezeichnet.
		 */
		for(int z=0;z<schnittpunkte.length-1;z++){
			//Die Anfangswerte werden statisch gesetzt
			x[0] = virtX2RealX(schnittpunkte[z]);
			nextSchnittpunkt=virtX2RealX(schnittpunkte[z + 1]);
			y[0] = virtY2RealY(erloes.berechne(schnittpunkte[z]));
			x[1] = x[0] + 1;
			x[2] = x[1];
			y[1] = virtY2RealY(kosten.berechne(realX2VirtX(x[1])));
			y[2] = virtY2RealY(erloes.berechne(realX2VirtX(x[2])));
			if (y[0] >= y[1]) {
				g.setColor(Color.GREEN);
			} else {
				g.setColor(Color.RED);
			}
			int i = 1;
			
			//Hier wird nach einem Algorithmus bis zum nächsten Schnittpunkt vorgegangen, in dem drei Punkte immer ein Polygon bilden und dieses mit der jeweiligen Farbe gefüllt wird.
			while (x[2] < nextSchnittpunkt) {
				if (kosten.berechne(realX2VirtX(x[2])) <= erloes
						.berechne(realX2VirtX(x[2]))) {
					g.setColor(Color.GREEN);
				} else {
					g.setColor(Color.RED);
				}
				g.fillPolygon(x, y, 3);
				x[0] = x[1];
				x[1] = x[2];
				x[2] += 2;
				y[0] = y[1];
				y[1] = y[2];
				if (i % 2 != 0) {
					y[2] = virtY2RealY(kosten.berechne(realX2VirtX(x[2])));
				} else {
					y[2] = virtY2RealY(erloes.berechne(realX2VirtX(x[2])));
				}
				i++;
			}
			x[2] = virtX2RealX(schnittpunkte[z + 1]);
			y[2] = virtY2RealY(kosten.berechne(schnittpunkte[z + 1]));
			g.fillPolygon(x, y, 3);
		}
		
	}
	
	/**
	 * Projeziert einen x-Wert des statischen Koordinatensystem des Fensters auf einen x-Wert des virtuellen Koordinatensystem mit den globalen Parametern
	 * @param x zu projezierednder Wert
	 * @return x-Wert auf virtuellen für Nutzer sichtbaren Koordinatensystem
	 */
	private double realX2VirtX(int x){
		return (x-middlePointX)*EinheitProPixelX;
	}
	/**
	 * Projeziert einen y-Wert  des virtuellen Koordinatensystem mit den globalen Parametern auf einen y-Wert des statischen Koordinatensystem des Fensters
	 * @param y zu projezierednder Wert
	 * @return y-Wert des statischen Koordinatensystems des Fensters mit dem z.B. gezeichnet wird
	 */
	private int virtY2RealY(double y){
		return (int)((y * (-1) + middlePointY*EinheitProPixelY) / EinheitProPixelY + 0.5);
	}

	/**
	 * Projeziert einen y-Wert des statischen Koordinatensystem von des Fensters auf einen y-Wert des virtuellen Koordinatensystem mit den globalen Parametern
	 * @param y zu projezierednder Wert
	 * @return y-Wert auf virtuellen für Nutzer sichtbaren Koordinatensystem
	 */
	@SuppressWarnings("unused")
	private double realY2VirtY(int y){
		return (y-middlePointY)*(-1)*EinheitProPixelY;
	}
	/**
	 * Projeziert einen x-Wert  des virtuellen Koordinatensystem mit den globalen Parametern auf einen x-Wert des statischen Koordinatensystem des Fensters
	 * @param x zu projezierednder Wert
	 * @return y-Wert des statischen Koordinatensystems des Fensters mit dem z.B. gezeichnet wird
	 */
	private int virtX2RealX(double x){
		return (int)((x + middlePointX*EinheitProPixelX) / EinheitProPixelX + 0.5);
	}
	/**
	 * Diese Methode veraendert den Mittelpunkt um die  x- und y-Werte.
	 * 
	 * @param xDifference
	 *            Wertaenderung in x-Richtung
	 * @param yDifference
	 *            Wertaenderung in y-Richtung
	 */
	public void setMiddlePoint(int xDifference, int yDifference) {
		this.middlePointX += xDifference;
		this.middlePointY += yDifference;
	}
	
	/**
	 * Setzt die aktuellen Einheiten Pro Pixel in x-Richtung neu.
	 * 
	 * @param PixelProEinheit Uebergeben wird alllerdings eine Anzahl an Pixeln, die eine Einheit bilden sollen. 
	 */
	public void setEinheitProPixelX(double PixelProEinheit) {
		this.EinheitProPixelX = PixelProEinheit / abstand;
	}
	/**
	 * Setzt die aktuellen Einheiten Pro Pixel in y-Richtung neu.
	 * 
	 * @param PixelProEinheit Uebergeben wird alllerdings eine Anzahl an Pixeln, die eine Einheit bilden sollen. 
	 */
	public void setEinheitProPixelY(double PixelProEinheit) {
		this.EinheitProPixelY = PixelProEinheit / abstand;
	}
	/**
	 * Setzt den globalen Wert von Markierungen auf True oder Flase, abhaengig davon ob er bereits ture oder false ist.
	 */
	public void toogleMarkierung(){
		markierungen = !markierungen;
	}
	/**
	 * Setzt den globalen Wert 'difference' auf True oder False.
	 * Abhaengig von diesem Wert wird die Differenzfunktion gezeichnet oder nicht.
	 */
	public void toogleDifference(){
		difference = !difference;
	}
	
	
	/**
	 * Diese Funktion setzt alle globalen Werte so, dass das Koordinatensystem in dem angegebenen Intervall mit einer vernünftigen Skalierung sichtbar wird.
	 * 
	 * @param von Intervallanfang
	 * @param bis Intervallende
	 * @return Um die Skalierung auch auf die Skalierungsleisten der Oberfläche scihtbar zu machen, wird der neue Wert PixelProEinheit zurückgegeben
	 * @throws IllegalArgumentException Sollte das eingegebene Intervall zu klein sein oder das Intervallende kleiner als der Anfang, wird diese Exception geschmissen, die von der Oberflöche gefangen und ausgewertet werden muss.
	 */
	public double setIntervall(double von, double bis) throws IllegalArgumentException{
		if(bis <= von){
			throw new IllegalArgumentException("Erstes Argument muss groesser sein als Zweites");
		}
		
		this.EinheitProPixelX=(bis-von)/(this.getWidth()-2*(randAbstand+10));
		if(EinheitProPixelX < 0.01/abstand){
			throw new IllegalArgumentException("Zu kleiner Wertebereich!");
		}
		this.middlePointX=middlePointX  - virtX2RealX(von) + randAbstand;
		this.middlePointY=this.getHeight()/2;
		
		return EinheitProPixelX*abstand;
	}
	/**
	 * Aendert die aktuell ausgewaehlte Funktion.
	 * 
	 */
	public void toogleAktFunktionen() {
		if(this.erloesFunktion != null && this.kostenFunktion==null){
			erloesFunktion.toogleAktFunktion();
		}
		else if(this.erloesFunktion == null && this.kostenFunktion!=null){
			this.kostenFunktion.toogleAktFunktion();
		}
		else if(this.erloesFunktion == null && this.kostenFunktion==null){
			JOptionPane.showMessageDialog(null, "Sie muessen zunaechst eine gueltige Funktion eingeben","Keine Funktion angegeben",JOptionPane.WARNING_MESSAGE);
		}
		else{
			this.kostenFunktion.toogleAktFunktion();
			this.erloesFunktion.toogleAktFunktion();
		}
	}
	/**
	 * Gibt zu der ausgewaehlten Funktion den y-Wert des uebergebeben x-Wertes zurueck
	 * @param x
	 * @return
	 * @throws NullPointerException
	 */
	public double getYofAktFunktion(double x) throws NullPointerException{
		
		if(kostenFunktion !=null && kostenFunktion.isAktFunktion()){
			return kostenFunktion.berechne(x);
		}
		else if(erloesFunktion != null && erloesFunktion.isAktFunktion()){
			return erloesFunktion.berechne(x);
		}
		else{
			throw new NullPointerException("Keine gueltige Funktion angegeben oder ausgewaehlt\nVersuchen Sie es mit druecken von Umschalten");
	
		}
	}
	
	/**
	 * Setzt die Erloesfunktion
	 * @param f Erloesfunktion vom eigenem Typ Funktion
	 */
	public void setErloesF(Funktion f){
		this.erloesFunktion=f;
		if(!this.erloesFunktion.isAktFunktion()){
			this.erloesFunktion.toogleAktFunktion();
		}
		if(this.kostenFunktion!=null && this.kostenFunktion.isAktFunktion()){
			this.kostenFunktion.toogleAktFunktion();
		}
		this.repaint();
	}
	/**
	 * setzt die Kostenfunktion
	 * @param f Kostenfunktion vom eigenem Typ Funktion
	 */
	public void setKostenF(Funktion f){
		this.kostenFunktion=f;
		if(!this.kostenFunktion.isAktFunktion()){
			this.kostenFunktion.toogleAktFunktion();
		}
		if(this.erloesFunktion!=null && this.erloesFunktion.isAktFunktion()){
			this.erloesFunktion.toogleAktFunktion();
		}
		this.repaint();
	}
	/**
	 * Ueberprueft, ob beide Funktionen gesetzt sind
	 * @return Liefert True zurueck falls beide Funktionen gesetzt sind. ANsonsten False
	 */
	public boolean areBothFunctionsSet(){
		if(this.erloesFunktion==null || this.kostenFunktion==null){
			return false;
		}
		return true;
	}
	/**
	 * Prueft ob die Erloesfunktion gesetzt ist
	 * @return True, wenn Erloesfunktion gesetzt ist, sonst false
	 */
	public boolean isErloesFunktion(){
		return (this.erloesFunktion!=null);
	}
	/**
	 * Prueft ob die Kostenfunktion gesetzt ist
	 * @return True, wenn Kostenfunktion gesetzt ist, sonst false
	 */
	public boolean isKostenFunktion(){
		return (this.kostenFunktion!=null);
	}
	
	/**
	 * Funktion, die die Differenzfunktion zeichnet
	 * @param g Graphics-Komponente auf der gezeichnet werden soll.
	 */
	private void drawDiff(Graphics g){
		float HSBColor[] = Color.RGBtoHSB(159, 81, 131, null);
		g.setColor(Color.getHSBColor(HSBColor[0],HSBColor[1],HSBColor[2]));
		this.zeichnePunkte(g, logik.getVergleich().getDiffFunktion().getWerte());
	}
	/**
	 * Zeichnet den maximalen Erloes der Kosten- und Erloesfunktion.
	 * @param g Graphics-Komponente auf der gezeichnet werden soll. 
	 */
	private void drawMaxErloes(Graphics g){
		float HSBColor[] = Color.RGBtoHSB(40, 117, 45, null);
		g.setColor(Color.getHSBColor(HSBColor[0],HSBColor[1],HSBColor[2]));
		double maxErloes[] = logik.getVergleich().getMaxErlos();
		System.out.println("maxErloes: "+maxErloes[0]);
		g.drawLine(virtX2RealX(maxErloes[0]), 20, virtX2RealX(maxErloes[0]), this.getHeight()-20);
		g.drawString("max. Erloes",virtX2RealX(maxErloes[0])+10, virtY2RealY(maxErloes[1])+10);
	}
	/**
	 * Kennzeichnet die Schnittpunkte dder beiden Funktionen
	 * @param g Graphics-Komponente auf der gezeichnet werden soll.
	 */
	private void drawSchnittpunkte(Graphics g){
		float HSBColor[] = Color.RGBtoHSB(8, 48, 99, null);
		g.setColor(Color.getHSBColor(HSBColor[0],HSBColor[1],HSBColor[2]));
		double schnittpunkte[] = logik.getVergleich().getSchnitteX();
		for(double i : schnittpunkte){
			g.drawLine(virtX2RealX(i), 20, virtX2RealX(i), this.getHeight()-20);
		}
	}
	/**
	 * Kennzeichnet den Maximalen Verlust
	 * @param g Graphics-Komponente auf der gezeichnet werden soll.
	 */
	private void drawMaxVerlust(Graphics g){
		float HSBColor[] = Color.RGBtoHSB(168, 0, 0, null);
		g.setColor(Color.getHSBColor(HSBColor[0],HSBColor[1],HSBColor[2]));
		double getExt[][] = logik.getAuswertungKosten().getExt();
		for(int i=0; i<getExt.length;i++){
			g.drawLine(virtX2RealX(getExt[i][0]), 20, virtX2RealX(getExt[i][0]), this.getHeight()-20);
			g.drawString("max. Verlust",virtX2RealX(getExt[i][0])+10, virtY2RealY(getExt[i][1])+10);
		}
	}
	/**
	 * Kennzeichnet den Maximalen Gewinn
	 * @param g Graphics-Komponente auf der gezeichnet werden soll.
	 */
	private void drawMaxGewinn(Graphics g){
		float HSBColor[] = Color.RGBtoHSB(45, 125, 63, null);
		g.setColor(Color.getHSBColor(HSBColor[0],HSBColor[1],HSBColor[2]));
		double getExt[][] = logik.getAuswertungErloes().getExt();
		for(int i=0; i<getExt.length;i++){
			g.drawLine(virtX2RealX(getExt[i][0]), 20, virtX2RealX(getExt[i][0]), this.getHeight()-20);
			g.drawString("max. Gewinn",virtX2RealX(getExt[i][0])+10, virtY2RealY(getExt[i][1])+10);
		}
	}

}
